package jp.co.toshiba.ffsa.service.cslt;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.security.Key;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;

import jp.co.toshiba.ffsa.dto.LoginDto;
import jp.co.toshiba.ffsa.entity.User;
import jp.co.toshiba.ffsa.form.cslt.Cslt101Form;
import jp.co.toshiba.ffsa.service.common.ConstantValue;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.seasar.extension.jdbc.JdbcManager;
import org.seasar.extension.jdbc.where.SimpleWhere;
import org.seasar.framework.container.SingletonS2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.struts.util.MessageResourcesUtil;
import org.seasar.struts.util.RequestUtil;
import org.seasar.struts.util.ResponseUtil;

/**
 * 限定公開資料画面Serviceクラス
 * @author (NPC)
 */
public class Cslt101Service {
    /** フォームリスト */
    public List<Cslt101Form> cslt101FormList;
    /** ファイルサイズリスト */
    public List<String> fileSize;
    /** 7桁数字連番（自動発番）*/
    private String userId;
    /** カタログリスト */
    private ArrayList<String> catalogList;

    /**
     * CSVファイルから資料の情報を取得
     * @return successFlag 検索パスワードが履歴と重複チェック
     * @throws Exception エラー
     */
    public List<Cslt101Form> readCsv() throws Exception{

        cslt101FormList = new ArrayList<Cslt101Form>();
        setUserId(((LoginDto)RequestUtil.getRequest().getSession().getAttribute("login_dto")).getUserID());
        User getUser = getUser();

        try {
            // CSVデータファイル
            File csv = new File(MessageResourcesUtil.getMessage("document.ltd.folderPath") + "meta_data_ltd.csv");
            FileInputStream csvFileInputStream = new FileInputStream(csv);
            InputStreamReader csvInputStreamReader = new InputStreamReader(csvFileInputStream);
            BufferedReader buffer = new BufferedReader(csvInputStreamReader);

            String line = "";
            String fileName = "";
            while ((line = buffer.readLine()) != null) {
                line = line.replaceAll("\"","");
                StringTokenizer stringTokenizer = new StringTokenizer(line, ",");
                while(stringTokenizer.hasMoreTokens()) {
                    Cslt101Form cslt101Form = new Cslt101Form();
                    cslt101Form.setCatalog(stringTokenizer.nextToken().toString());
                    fileName = stringTokenizer.nextToken().toString();
                    cslt101Form.setFileName(fileName);
                    SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
                    Date  date = format.parse(stringTokenizer.nextToken().toString());
                    cslt101Form.setUpdateDate(date);
                    cslt101Form.setLevel(stringTokenizer.nextToken().toString());
                    cslt101Form.setExplanation(stringTokenizer.nextToken().toString());
                    cslt101Form.setFileSize(fileSize(fileName));
                    cslt101Form.setUserLevel(getUser.authority);
                    cslt101FormList.add(cslt101Form);
                }
            }
            IOUtils.closeQuietly(csvFileInputStream);
            IOUtils.closeQuietly(csvInputStreamReader);
            IOUtils.closeQuietly(buffer);

        } catch (FileNotFoundException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }
        return cslt101FormList;
    }

    /**
     * 限定公開資料ダウンロード
     * @return successFlag 限定公開資料ダウンロード処理チェック
     * @throws Exception エラー
     */
    public boolean downloadFile(String fileName) throws Exception{
        // ダウンロード処理チェック
        boolean successFlag = false;
        HttpServletResponse response = ResponseUtil.getResponse();
        // ファイルパス
        File file = new File(MessageResourcesUtil.getMessage("document.ltd.folderPath") + fileName);

        FileInputStream fis = null;
        CipherInputStream cis = null;
        InputStream in = null;
        OutputStream out = null;

        try {
            ResponseUtil.getResponse().setContentType("application/octet-stream");
            ResponseUtil.getResponse().setHeader("Content-disposition","attachment; filename=" + URLEncoder.encode(fileName,MessageResourcesUtil.getMessage("charset")));

            Key key = new SecretKeySpec(DigestUtils.sha256(ConstantValue.key), "AES");
            fis = new FileInputStream(file);
            byte[] iv = new byte[16];
            fis.read(iv);
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec ivspec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, key, ivspec);
            cis = new CipherInputStream(fis, cipher);

            in = new BufferedInputStream(cis);
            out = ResponseUtil.getResponse().getOutputStream();
            int data;
            byte[] b = new byte[1024];
            while ((data = in.read(b, 0, 1024)) != -1) {
                out.write(b, 0, data);
            }

            successFlag = true;

        } catch (Exception e) {
            //ファイルダウンロード用の出力済みHTTPヘッダをリセット。
            successFlag = false;
            response.reset();
            throw e;

        } finally {
            IOUtils.closeQuietly(fis);
            IOUtils.closeQuietly(cis);
            IOUtils.closeQuietly(in);
            IOUtils.closeQuietly(out);
        }

        return successFlag;

    }

    /**
     * 限定公開資料のサイズを確認
     * @return fileSize ファイルサイズ
     */
    public String fileSize(String fileName) {
        String fileSize = "";
        DecimalFormat decimalFormat =new DecimalFormat("#.##");

        // ファイルパス
        File file = new File(MessageResourcesUtil.getMessage("document.ltd.folderPath") + fileName);
        long fileSizeByte = file.length();
        double fileSizeKB=Double.valueOf(decimalFormat.format(fileSizeByte /1024));
        double fileSizeMB=Double.valueOf(decimalFormat.format(fileSizeByte /(1024*1024)));
        double fileSizeGB=Double.valueOf(decimalFormat.format(fileSizeByte /(1024*1024*1024)));

        if(fileSizeGB > 1){
            fileSize = (int) fileSizeGB + "G";
        }else if(fileSizeMB > 1){
            fileSize = (int) fileSizeMB + "M";
        }else if(fileSizeKB >1){
            fileSize = (int) fileSizeKB + "K";
        }else{
            fileSize =  String.valueOf(fileSizeByte) ;
        }
        return fileSize;
    }

    /**
     * 限定公開資料のレベル別公開制御を行う
     */
    public List<String> calcCatalogByLevel() throws Exception {
        catalogList = new ArrayList<String>();

        setUserId(((LoginDto)RequestUtil.getRequest().getSession().getAttribute("login_dto")).getUserID());
        User getUser = getUser();

        // レベル別の公開制御を行う
        if(!getUser.authority.equals("3")){
            for(Cslt101Form list : cslt101FormList){
                if(list.getLevel().equals("2")) catalogList.add(list.getCatalog());
            }
        }else{
            for(Cslt101Form list : cslt101FormList){
                if(list.getLevel().equals("2") || list.getLevel().equals("3")) catalogList.add(list.getCatalog());
            }
        }

        // カタログの重複の処理
        for (int i = 0; i < catalogList.size() - 1; i++) {
            for (int j = i + 1; j < catalogList.size();) {
                if (catalogList.get(i).equals(catalogList.get(j))) {
                    catalogList.remove(j);
                } else {
                    ++j;
                }
            }
        }
        return catalogList;
    }

    /**
     * ユーザー情報取得処理
     * @throws Exception
     */
    public User getUser() throws Exception{

        User user;
        // S2Container初期化
        SingletonS2ContainerFactory.init();

        // S2ContainerからJdbcManagerを取得
        JdbcManager jdbcManager = SingletonS2Container.getComponent(JdbcManager.class);
        try{

            // 検索条件
            SimpleWhere swh = new SimpleWhere().eq("userID", userId)
                                               .eq("deleteFlag", ConstantValue.deleteFlagEnabled);

            // 一覧取得
            user= jdbcManager.from(User.class)
                             .where(swh)
                             .getSingleResult()
                             ;

        }catch(Exception e){
            throw e;
        }

        return user;
    }

    /**
     * @param userId セットする
     */
    public void setUserId(String userId) {this.userId = userId;}

}
